package ThreadCurr;

/**
 * 多线程并发安全问题
 * 当多个线程并发操作同一临界资源，由于线程切换的时机不确定，导致操作顺序出现
 * 混乱，严重时可能导致系统瘫痪。
 * 临界资源:同时只能被单一线程访问操作过程的资源。
 */
public class SyncDemo {
    public static void main(String[] args) {
        Table table2 = new Table();
        Table table1 = new Table();
      //  Table table=new Table();
        Thread t1 = new Thread(){
            public void run(){
                while(true){
                    int bean = table1.getBean();
                  //  int bean = table.getBean();
                    Thread.yield();
                    System.out.println(getName()+":"+bean);
                }
            }
        };
        Thread t2 = new Thread(){
            public void run(){
                while(true){
                    int bean = table2.getBean();
                   // int bean = table.getBean();
                    /*
                        static void yield()
                        线程提供的这个静态方法作用是让执行该方法的线程
                        主动放弃本次时间片。
                        这里使用它的目的是模拟执行到这里CPU没有时间了，发生
                        线程切换，来看并发安全问题的产生。
                     */
                    Thread.yield();
                    System.out.println(getName()+":"+bean);
                }
            }
        };
        t1.start();
        t2.start();
    }
}

class Table{
    private static int beans = 20;//桌子上有20个豆子
    // synchronized 修饰的方法变为同步方法， 按照顺序一个一个的执行，一个执行结束另一个才可以继续进行
    /**
     * 当一个方法使用synchronized修饰后，这个方法称为同步方法，多个线程不能
     * 同时执行该方法。
     * 将多个线程并发操作临界资源的过程改为同步操作就可以有效的解决多线程并发
     * 安全问题。
     * 相当于让多个线程从原来的抢着操作改为排队操作。
     */
    public  int getBean(){
       // synchronized(this){ 不可以
        synchronized(Table.class){
        //synchronized(Boo.class){
            if(beans==0){
                throw new RuntimeException("没有豆子了!");
            }
            Thread.yield();
            return beans--;
        }

    }
}